#include "GapVector.h"
#include <assert.h>
#include "Util.h"

GapVector::GapVector(int initLength):buffer(0), arrayLength(0), g0_(0), g1_(0){
	arrayLength = max(10, initLength);
	buffer = new char[arrayLength];
	g1_ = arrayLength;
}
GapVector::~GapVector(){
	if(buffer){
		delete[] buffer;
	}
}

string GapVector::GetString(size_t offset, size_t len)const {
	if(!len){
		return "";
	}
	size_t index = Offset2Index(offset);
	assert(InPart1(index) || InPart2(index));//起始索引, 不能在gap中
	assert(index + len -1 < arrayLength); //结束索引, 必须有效
	if(InPart1(index) ){
		if(!InPart1(index + len-1)){// 结束索引不在part1
			size_t lenP1 = g0_ - index;
			size_t lenP2 = len - lenP1;
			return string(buffer + index, lenP1) + string(buffer + g1_, lenP2);
		}
	}
	return string(buffer + index, len);
}

void GapVector::Remove(size_t offset, size_t rmSize){
	if(!rmSize){
		return;
	}
	size_t index  = Offset2Index(offset);
	assert(InPart1(index) || InPart2(index));//起始索引, 不能在gap中
	assert(index + rmSize -1 < arrayLength); //结束索引, 必须有效

	size_t gw = g1_ - g0_;
	if(InPart1(index) &&  !InPart1(index + rmSize)){
		OnIndexRemove(index, g0_);
		OnIndexRemove(g1_, index + gw + rmSize );//g1_, g1_ + (rmSize - (g0_ - index) )
		g0_ = index;
		g1_ = g0_+ gw + rmSize;
	}else{
		if(g0_ != index){
			if(InPart1(index)){
				OnIndexRemove(index, index + rmSize);
				size_t tocopy = g0_-index - rmSize;
				MoveData(g1_ - tocopy, index + rmSize, tocopy);
				g0_ = index;
				g1_ -= tocopy;
			}else{
				OnIndexRemove(index, index + rmSize);
				MoveData(g0_, g1_, index - g1_);
				g1_ = index + rmSize;
				g0_ = index - gw;
			}
		}else{
			OnIndexRemove(g1_, g1_ + rmSize);
			g1_ = g1_ + rmSize;
		}
	}
}
void GapVector::Insert(size_t offset, const char additems[], size_t addSize){
	if(!addSize){
		return;
	}
	assert(offset <= Length());
	if(addSize >= g1_ - g0_){//扩容
		size_t len2 = arrayLength - g1_;
		size_t newArraySize = GetNewArraySize(arrayLength + addSize - (g1_ - g0_));
		char* arr = new char[newArraySize];
		ArrayCopy(buffer, 0, arr, 0, arrayLength);
		delete[] buffer;
		buffer = arr;
		arrayLength = newArraySize;
		MoveData(newArraySize - len2, g1_, len2);
		g1_ =newArraySize - len2;
	}
	if(g0_ == offset){
		ArrayCopy(additems, 0, buffer, g0_, addSize);
		g0_ += addSize;
	}else{
		size_t index = Offset2Index(offset);
		size_t gw = g1_ - g0_;
		if(InPart1(index)){
			MoveData(index + gw, index, g0_-index);
			g0_ = index;
			g1_ = index + gw;
			ArrayCopy(additems, 0, buffer, g0_, addSize);
			g0_ += addSize;
		}else{
			size_t delta = index - g1_;
			MoveData(g0_, g1_, delta);
			g1_ = index;
			g0_ = g1_ - gw;
			ArrayCopy(additems, 0, buffer, g1_-addSize, addSize);
			g1_ -= addSize;
		}	
	}
}
void GapVector::Insert(size_t offset, const string& s){
	Insert(offset, s.c_str(), s.length());
}
void GapVector::MoveData(size_t destIndex, size_t srcIndex, size_t length){
	if(destIndex == srcIndex || !length){
		return;
	}
	ArrayCopy(buffer,  srcIndex, buffer, destIndex,  length);
	OnIndexChange(srcIndex, srcIndex + length, destIndex - srcIndex);
}
void GapVector::OnIndexChange(size_t fromIndex, size_t toIndex, int delta){

}
void GapVector::OnIndexRemove(size_t fromIndex, size_t toIndex){

}
size_t GapVector::GetNewArraySize(size_t reqSize)const{
	if( reqSize < GROWTH_SIZE){
		return (reqSize +1) *2;
	}
	return reqSize + GROWTH_SIZE;
}

int GapVector::Length() const{
	return arrayLength - (g1_ - g0_);
}

size_t GapVector::Offset2Index(size_t offset)const{
	assert(offset < Length());
	return offset < g0_ ? offset : offset + g1_-g0_;
}
size_t GapVector::Index2Offset(size_t index)const{
	assert(index <g0_ || index >=g1_);
	assert(index < arrayLength);
	return index < g0_ ? index : index -(g1_ - g0_);
}

bool GapVector::InPart1(size_t index)const{
	return index <g0_;
}
bool GapVector::InPart2(size_t index)const{
	return index >=g1_ && index < arrayLength;
}

